package com.be.beadmin.system.impl.ProductQualityServiceImpl;

import com.be.beadmin.basicData.dto.output.UserEx;
import com.be.beadmin.basicData.entity.User;
import com.be.beadmin.basicData.service.UserService;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.product.dto.WorkOrderProductPlanDto;
import com.be.beadmin.product.dto.input.ScheduleDto;
import com.be.beadmin.product.entity.ProductManufactInfor;
import com.be.beadmin.product.entity.UserWorkHourInfo;
import com.be.beadmin.product.entity.WorkOrderInfor;
import com.be.beadmin.product.repository.ProductManufactInforRepository;
import com.be.beadmin.product.repository.UserWorkHourInfoRepository;
import com.be.beadmin.product.repository.WorkOrderInforRepository;
import com.be.beadmin.product.service.PlantCapacityCalendarService;
import com.be.beadmin.product.service.ProductManufactInforService;
import com.be.beadmin.product.service.UserWorkHourInfoService;
import com.be.beadmin.product.task.WorkingHoursCountTask;
import com.be.beadmin.project.entity.*;
import com.be.beadmin.project.repository.*;
import com.be.beadmin.project.service.PlanStageService;
import com.be.beadmin.quality.entity.InspectionTask;
import com.be.beadmin.quality.entity.InspectionTemplate;
import com.be.beadmin.quality.entity.ProductQuality;
import com.be.beadmin.quality.entity.ProductSelfCheckInfor;
import com.be.beadmin.quality.repository.InspectionTaskRepository;
import com.be.beadmin.quality.repository.InspectionTemplateRepository;
import com.be.beadmin.quality.repository.ProductSelfCheckInforRepository;
import com.be.beadmin.quality.service.InspectionTaskService;
import com.be.beadmin.quality.service.ProductQualityService;
import com.be.beadmin.service.entity.NotifyInfo;
import com.be.beadmin.service.repository.FactoryCalendarRepository;
import com.be.beadmin.service.repository.NotifyInfoRepository;
import com.be.beadmin.service.service.NotifyTemplateInfoService;
import com.be.beadmin.service.task.TaskThreadPool;
import com.be.beadmin.system.service.ProductMaterialService.WorkOrderInforPmService;
import com.be.beadmin.system.service.ProductQualityService.ProductManufactInforPqService;
import com.be.beadmin.system.task.ReleaseWoTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: Jiaming Zheng
 * @Date: Create in 15:08 2023/6/20
 * @Modified By:
 **/
@Service
public class ProductManufactInforPqServiceImpl implements ProductManufactInforPqService {
    @Autowired
    private ProductManufactInforRepository productManufactInforRepository;
    @Autowired
    private PlantCapacityCalendarService plantCapacityCalendarService;
    @Autowired
    private FactoryCalendarRepository factoryCalendarRepository;
    @Autowired
    private ProductQualityService productQualityService;
    @Autowired
    private BatchProductRepository batchProductRepository;
    @Autowired
    private BatchPlanRepository batchPlanRepository;
    @Autowired
    private InspectionTaskService inspectionTaskService;
    @Autowired
    private InspectionTaskRepository inspectionTaskRepository;
    @Autowired
    private ProductSelfCheckInforRepository productSelfCheckInforRepository;


    @Autowired
    private TaskThreadPool taskThreadPool;
    @Autowired
    private ProductManufactInforService productManufactInforService;
    @Autowired
    private InspectionTemplateRepository inspectionTemplateRepository;

    @Autowired
    private WorkOrderInforRepository workOrderInforRepository;

    @Autowired
    private UserService userService;


    @Autowired
    private UserWorkHourInfoService userWorkHourInfoService;

    @Autowired
    private WorkOrderInforPmService workOrderInforPmService;

    @Autowired
    private UserWorkHourInfoRepository userWorkHourInfoRepository;
    @Autowired
    private InfoRepository infoRepository;


    @Autowired
    private TeamInfoRepository teamInfoRepository;

    @Autowired
    private NotifyTemplateInfoService notifyTemplateInfoService;

    @Autowired
    private NotifyInfoRepository notifyInfoRepository;

    @Autowired
    private PlanStageRepository planStageRepository;

    @Autowired
    private PlanStageService planStageService;
    /**
     * 开始工序执行 -- 每个用户都有一个单独的
     *
     * @param productManufactInforId
     * @return
     */
    @Override
    public int startProductManufactExec(HttpServletRequest request, String productManufactInforId) {

        // 找到该工序
        ProductManufactInfor productManufactInfor = productManufactInforRepository.findProductManufactInforByIdAndDelete(productManufactInforId, 0);
        if (productManufactInfor == null) {
            throw new BeadminException("未找到该工序");
        }
        // 获取该工序的工单
        WorkOrderInfor workOrderInfor = workOrderInforRepository.findWorkOrderInforByBatchProductIdAndDelete(productManufactInfor.getBatchProductId(), 0);
        // 获取该工单第一道工序的序号
        int firstSeqAndDelete = productManufactInforRepository.findProcessFirstSeqAndDelete(productManufactInfor.getBatchProductId(), 0);
        // 如果为第一道工序，检查是否能开始工序
        if (productManufactInfor.getSequence() == firstSeqAndDelete) { // 如果是装配，首先得判断柜体入库检是否合格或者让步接收 / 同时分料工序完成
//            1. 柜体入库检
            List<ProductQuality> productQualityList = productQualityService.getProductQualityByBatchProduct(productManufactInfor.getBatchProductCode());
            if (productQualityList.size() == 0) {
                throw new BeadminException("柜体入场检验不合格，无法开始生成");
            }

//            2. 物料接收完成


        }

        // 前一项执行结束后一项才会执行
        if (productManufactInfor.getProcessStatus() == 0) { // 未开始执行
            for (ProductManufactInfor manufactInfor : productManufactInforRepository.findProductManufactInforsByBatchProductCodeAndIsProductionProcessAndSequenceIsLessThanAndDelete(productManufactInfor.getBatchProductCode(),1, productManufactInfor.getSequence(), 0)) {
                if (manufactInfor.getProcessStatus() != 3 ) {
                    throw new BeadminException("前面有工序未完成，请先完成前序工序【" + manufactInfor.getProcessName() + "】");
                }
            }

        }

        // 获取当前用户
        UserEx userEx = userService.viewBaseInfo(request);
        /**
         * 0 - 未开始
         * 1 - 已经开始
         * 3 - 已完成
         */
        // 获取所有人针对与该工序的状态
        int state = userWorkHourInfoService.viewProcessState(productManufactInfor);
        Date d= new Date();
        // 检查是否为该批次第一个执行的柜子， count大于零说明有已经开始执行的工序了
        int count1 = batchProductRepository.countExecutedProduct(productManufactInfor.getBatchProductId());
        // 如果为该批次的第一个执行的柜子，而且是第一道工序， 那么就更新批次的生产装配的开始时间
        if (count1 > 0 &&  state == 0) {
//            BatchProduct bp = batchProductRepository.findBatchProductByIdAndDelete(productManufactInfor.getBatchProductId(),0);
//            BatchPlan batchPlan = batchPlanRepository.findBatchPlanByIdAndDelete(bp.getBatchPlanId(), 0);
//            planStageRepository
//            String planId = batchProductRepository.findBatchPlanByBatchProductId(productManufactInfor.getBatchProductId());
            PlanStage planStage = planStageService.getPlanStageByBatchProductIdAndName(productManufactInfor.getBatchProductId(),"生产装配");
            planStage.setStageStartTime(d);
            planStageRepository.save(planStage);
        }
        // 第一次开始的时候还需要自动生成自检单 也没有其他的人开始计时，
        if (productManufactInfor.getProcessStatus() == 0 && state == 0) {

//            BatchProduct b = batchProductRepository.findBatchProductByIdAndDelete(productManufactInfor.getBatchProductId(), 0);
                ProductSelfCheckInfor productSelfCheckInforByProcessIdAndDelete = productSelfCheckInforRepository.findProductSelfCheckInforByProcessIdAndDelete(productManufactInforId, 0);
                // 如果没有自检单
                if (productSelfCheckInforByProcessIdAndDelete == null ) {
//                    if (productManufactInfor.getProcessName().contains("装配") || productManufactInfor.getProcessName().contains("接线") || productManufactInfor.getProcessName().contains("检验")) {
//
//                        ProductSelfCheckInfor productSelfCheckInfor = new ProductSelfCheckInfor();
//                        productSelfCheckInfor.setBatchProductId(productManufactInfor.getBatchProductId());
//                        productSelfCheckInfor.setBatchProductCode(productManufactInfor.getBatchProductCode());
//                        productSelfCheckInfor.setProcessId(productManufactInforId);
//                        productSelfCheckInfor.setProcessCode(productManufactInfor.getProcessCode());
//                        productSelfCheckInfor.setProcessName(productManufactInfor.getProcessName());
//
//
//                        if (productSelfCheckInfor.getProcessName().contains("装配")) {
//                            InspectionTemplate template = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndStateAndDeleteAndNameLike(workOrderInfor.getProductType(), "1", 0, "%装配%");
//                            if (template == null) throw new BeadminException("未找到已发布的装配工序检验表模板");
//                            productSelfCheckInfor.setSelfCheckTemplate(template.getId());
//                            // 生成装配自检单
//                            InspectionTask inspectionTask = inspectionTaskService.generateInspectionTask(productManufactInfor, template);
//                            productSelfCheckInfor.setInspectionTaskId(inspectionTask.getId());
////                        if ()
//                        }
//
//                        if (productSelfCheckInfor.getProcessName().contains("接线")) {
//                            InspectionTemplate template = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndStateAndDeleteAndNameLike(workOrderInfor.getProductType(), "1", 0, "%接线%");
//                            if (template == null) throw new BeadminException("未找到已发布的接线工序检验表模板");
//                            productSelfCheckInfor.setSelfCheckTemplate(template.getId());
//                            // 生成接线自检单
//                            InspectionTask inspectionTask = inspectionTaskService.generateInspectionTask(productManufactInfor, template);
//                            productSelfCheckInfor.setInspectionTaskId(inspectionTask.getId());
//
//                        }
//
//                        if (productSelfCheckInfor.getProcessName().contains("检验")) {
//                            InspectionTemplate template = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndStateAndDeleteAndNameLike(workOrderInfor.getProductType(), "1", 0, "%检验过程%");
//                            if (template == null) throw new BeadminException("未找到已发布的检验工序检验表模板");
//                            productSelfCheckInfor.setSelfCheckTemplate(template.getId());
//                            // 生成检验自检单
//                            InspectionTask inspectionTask = inspectionTaskService.generateInspectionTask(productManufactInfor, template);
//                            productSelfCheckInfor.setInspectionTaskId(inspectionTask.getId());
//
//                        }
//                        productSelfCheckInforRepository.save(productSelfCheckInfor);
//                    }

                    //不限制装配、接线、检验 三道工序  的写法
                    String processNameForInspection  = productManufactInfor.getProcessName();
                    InspectionTemplate inspectionTemplate = inspectionTemplateRepository.findInspectionTemplateByProductTypeAndProcessNameAndStateAndDelete(workOrderInfor.getProductType(),processNameForInspection,"1",0);
                    if (inspectionTemplate != null) {

                        ProductSelfCheckInfor productSelfCheckInfor = new ProductSelfCheckInfor();
                        productSelfCheckInfor.setBatchProductId(productManufactInfor.getBatchProductId());
                        productSelfCheckInfor.setBatchProductCode(productManufactInfor.getBatchProductCode());
                        productSelfCheckInfor.setProcessId(productManufactInforId);
                        productSelfCheckInfor.setProcessCode(productManufactInfor.getProcessCode());
                        productSelfCheckInfor.setProcessName(productManufactInfor.getProcessName());
                        productSelfCheckInfor.setSelfCheckTemplate(inspectionTemplate.getId());
                        // 生成接线自检单
                        InspectionTask inspectionTask = inspectionTaskService.generateInspectionTask(productManufactInfor, inspectionTemplate);
                        productSelfCheckInfor.setInspectionTaskId(inspectionTask.getId());
                        productSelfCheckInforRepository.save(productSelfCheckInfor);
                    }
                }
                // 生成终检单
                int lastSeqAndDelete = productManufactInforRepository.findProcessLastSeqAndDelete(productManufactInfor.getBatchProductId(), 0);
                // 是最后一道程序,生成终检单
                if (lastSeqAndDelete == productManufactInfor.getSequence()) {

                    System.out.println("正在生成终检单");

                    List<InspectionTask> taskList = inspectionTaskRepository.findInspectionTaskByWoAndTypeAndDelete(workOrderInfor.getWo(), "终检", 0);


                    if (taskList.size() > 1) {
//                throw new BeadminException("终检单超过一个了");
                    }
                    if (taskList.size() == 0) { // 如果有的话就不生成了
                        // 查找终检单模板
                        List<InspectionTemplate> templatelist = inspectionTemplateRepository.findInspectionTemplateByStateAndDeleteAndType("1", 0, "终检");
                        if (templatelist.size() == 0) throw new BeadminException("未找到已发布的终检检验表模板");
                        // 生成终检单
                        inspectionTaskService.generateFinishInspectionTask(workOrderInfor, templatelist.get(0));
//                    // 生成自检单
//                    InspectionTask inspectionTask = inspectionTaskService.generateInspectionTask(save, templatelist.get(0));
//                productSelfCheckInfor.setInspectionTaskId(inspectionTask.getId());
                    }
                }
            // 更改状态 工序
            productManufactInfor.setProcessStatus(1);// 执行中
            productManufactInfor.setManufactStartDate(d);
            if (productManufactInfor.getManufactStartDate() != null) {
                productManufactInfor.setManufactStartDate(d);
            }
            ProductManufactInfor save = productManufactInforRepository.save(productManufactInfor);
//            // 生成实际产能日历
//            plantCapacityCalendarService.generateRealCapacityCalendar(save);
            plantCapacityCalendarService.updateRealPlantCapCalenderByBatchPlan(save);

        }
        // 剩下是对这个人对于该工序的操作   前面已经把整条工序的状态都修改了，
        // 开始计时 给他们自己的计时
        UserWorkHourInfo userWorkHourInfo = userWorkHourInfoService.getUserWorkHourInfo(userEx, productManufactInforId);
        UserWorkHourInfo newUWHI;
        if (userWorkHourInfo != null) { // 暂停回来执行执行
            newUWHI = userWorkHourInfo;
        } else { // 第一次执行
            newUWHI = new UserWorkHourInfo();
            newUWHI.setUserId(userEx.getId());
            newUWHI.setUserName(userEx.getName());
            newUWHI.setManufactStartDate(d);
            newUWHI.setProcessId(productManufactInforId);
        }
        newUWHI.setProcessStatus(1); // 设置为正在执行
        userWorkHourInfoRepository.save(newUWHI);
        // 计时也开始
        userWorkHourInfoService.startTiming(newUWHI);

        // todo 若所开启工序为该批次的【第一个工单/柜体的第一道工序, 即 processStatus == 0的工序数量为总数量-1】，则更新该批次的生产装配实际开始时间

        List<String> batchProductIds = workOrderInforRepository.findWorkOrderInforByBatchPlanIdAndDelete(workOrderInfor.getBatchPlanId(), 0).stream().map(WorkOrderInfor::getBatchProductId).collect(Collectors.toList());
        List<ProductManufactInfor> batchProductManufactInfor = productManufactInforRepository.findProductManufactInforsByBatchProductIdInAndSequenceAndDelete(batchProductIds,firstSeqAndDelete,0);

        long count = batchProductManufactInfor.stream().filter(manufactInfor -> manufactInfor.getProcessStatus() == 0).count();

        if (count == batchProductManufactInfor.size()-1){
            PlanStage manufactAssembly = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(workOrderInfor.getBatchPlanId(), "生产装配", 0);
            manufactAssembly.setStageStartTime(new Date());
            planStageRepository.save(manufactAssembly);
        }

        return 0;
    }

    /**
     * 完成工序执行
     *
     * @param productManufactInforId
     * @return
     */
    @Transactional
    @Override
    public int finishProductManufactExec(HttpServletRequest request,String productManufactInforId) {


        ProductManufactInfor productManufactInfor = productManufactInforRepository.findProductManufactInforByIdAndDelete(productManufactInforId, 0);
        WorkOrderInfor workOrderInfor = workOrderInforRepository.findWorkOrderInforByBatchProductIdAndDelete(productManufactInfor.getBatchProductId(), 0);

        // 获取当前用户
        UserEx userEx = userService.viewBaseInfo(request);



        // 最后在判断是否为最后一个完成的用户

//        if (productManufactInfor == null) {
//            throw new BeadminException("未找到该工序");
//        }
//        if (productManufactInfor.getProcessStatus() == 3) {
//            throw new BeadminException("工序已经结束，无法再次结束");
//        }
//        if (productManufactInfor.getProcessStatus() == 0) {
//            throw new BeadminException("工序尚未开始，无法结束");
//        }
        // 1. 前置判断
        int state = userWorkHourInfoService.viewProcessStateExceptSelf(productManufactInfor,userEx);
        if (state == 3) { // 如果除了当前这个用户其他的用户都结束了都结束了整个工序就结束
            synchronized (ProductManufactInforPqServiceImpl.class) {
                    /**** 自检单提交 *****/
                    // 首先检查自检有没有上传或者提交， 才会完成。
                    for (InspectionTask inspectionTask : inspectionTaskRepository.findInspectionTasksByProcessIdAndDelete(productManufactInforId, 0)) {
                        if (inspectionTask.getState() == 0) {
                            throw new BeadminException("该工序的自检单还未上传，请先上传自检单");
                        }
                    }
                    /** 终检单提交 **/
                    // 检查是不是最后一道工序
                    int lastSeqAndDelete = productManufactInforRepository.findProcessLastSeqAndDelete(productManufactInfor.getBatchProductId(), 0);
                    // 最后一个工序完成前需要先终检
                    if (lastSeqAndDelete == productManufactInfor.getSequence()) {
                        for (InspectionTask inspectionTask : inspectionTaskRepository.findInspectionTaskByWoAndTypeAndDelete(workOrderInfor.getWo(), "终检", 0)) {
                            if (inspectionTask.getState() == 0) {
                                throw new BeadminException("最后一个工序完成前需要先终检，请先上传终检单");
                            }
                        }


                    }
            }


        }
        // 2. 最后将当前用户的计时完成结束 -- 得先检查

        UserWorkHourInfo userWorkHourInfo = userWorkHourInfoService.getUserWorkHourInfo(userEx, productManufactInforId);
        Date findate = new Date();
        if (userWorkHourInfo == null) return -1;
        userWorkHourInfoService.finishTiming(userWorkHourInfo,findate);
        userWorkHourInfo.setManufactEndDate(findate); // 设置结束时间
        userWorkHourInfo.setProcessStatus(3); // 设置为完成
        userWorkHourInfoRepository.save(userWorkHourInfo);
        // 3. 该工序的最终处理
        if (state == 3) {

            // 设置该工序的状态
            productManufactInfor.setProcessStatus(3);// 已完成
            productManufactInfor.setManufactEndDate(findate);
            ProductManufactInfor save = productManufactInforRepository.save(productManufactInfor);
//        // 生成实际产能日历
//        plantCapacityCalendarService.generateRealCapacityCalendar(productManufactInfor);
            plantCapacityCalendarService.updateRealPlantCapCalenderByBatchPlan(save);


            workOrderInfor.setState(2); // 工单完成
            workOrderInfor.setCloseTime(findate);
            workOrderInforRepository.save(workOrderInfor);


            // todo 若所完成工序为该批次的【最后一个工单/柜体的最后一道工序, 即 processStatus == 3的工序数量为总数量】，则更新该批次的生产装配实际结束时间
            int lastSeqAndDelete = productManufactInforRepository.findProcessLastSeqAndDelete(productManufactInfor.getBatchProductId(), 0);

            List<String> batchProductIds = workOrderInforRepository.findWorkOrderInforByBatchPlanIdAndDelete(workOrderInfor.getBatchPlanId(), 0).stream().map(WorkOrderInfor::getBatchProductId).collect(Collectors.toList());
            List<ProductManufactInfor> batchProductManufactInfor = productManufactInforRepository.findProductManufactInforsByBatchProductIdInAndSequenceAndDelete(batchProductIds,lastSeqAndDelete,0);

            long count = batchProductManufactInfor.stream().filter(manufactInfor -> manufactInfor.getProcessStatus() == 3).count();

            if (count == batchProductManufactInfor.size()){
                PlanStage manufactAssembly = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(workOrderInfor.getBatchPlanId(), "生产装配", 0);
                manufactAssembly.setStageEndTime(new Date());
                planStageRepository.save(manufactAssembly);
            }



            //工单自动关闭
            //--------------------------------------------
            //能够成功关闭工单
            // 生产经理 发送 关单关闭 通知给  项目成员+生产组长
            NotifyInfo notifyInfo =new NotifyInfo();
            notifyInfo.setModuleName("生产制造");
            notifyInfo.setFuncName("工单关闭");

            String wo=workOrderInfor.getWo();

            notifyInfo.setNotifyDesc("工单号["+wo+"]---工单已被关闭");
            notifyInfo.setNotifyType("通知");

            String infoId = workOrderInfor.getInfoId();
            Info info = infoRepository.findInfoByIdAndDelete(infoId,0);
            if(info!= null){
                String teamId = info.getTeamId();
                if(teamId!=null){
                    List<TeamInfo> teamInfoList = teamInfoRepository.findTeamInfoByTeamIdAndDelete(teamId,0);
                    TeamInfo projectManager =  teamInfoRepository.findTeamInfoByTeamIdAndCategoryAndDelete(teamId,"生产经理",0);
                    String senderName = "-";
                    String senderId="-";
                    if(projectManager!=null){
                        if(projectManager.getUserName()!=null){
                            senderName = projectManager.getUserName();
                        }
                        if(projectManager.getUserId()!=null){
                            senderId = projectManager.getUserId();
                        }
                    }
                    notifyInfo.setSenderName(senderName);
                    notifyInfo.setSenderId(senderId);
                    notifyInfo.setSendTime(workOrderInfor.getUpdateTime());
                    notifyInfo = notifyInfoRepository.save(notifyInfo);


                    Set<String> st =new HashSet<>();
                    for (TeamInfo teamInfo:teamInfoList){
                        String receiver = teamInfo.getUserName();
                        if(receiver!=null&&!st.contains(receiver)){
                            st.add(receiver);
                            notifyTemplateInfoService.sendNotify(notifyInfo,-1,receiver,teamInfo.getUserId());
                        }
                    }
                    //放最后
                    //--------------------------------------------
                }
            }


        }

        WorkingHoursCountTask workingHoursCountTask = new WorkingHoursCountTask();
        taskThreadPool.execute(workingHoursCountTask);
        // 除了这条柜子其他柜子都已经完成了， count1应该为0， 如果有不为0，说明有工序没有完成
        int count1 = batchProductRepository.countUnFinishExecutedProductExceptThis(productManufactInfor.getBatchProductId());
        // 那么就更新批次的生产装配的结束时间和打包入库的开始时间
        if (count1 == 0 &&  state == 3) {
//            BatchProduct bp = batchProductRepository.findBatchProductByIdAndDelete(productManufactInfor.getBatchProductId(),0);
//            BatchPlan batchPlan = batchPlanRepository.findBatchPlanByIdAndDelete(bp.getBatchPlanId(), 0);
//            planStageRepository
//            String planId = batchProductRepository.findBatchPlanByBatchProductId(productManufactInfor.getBatchProductId());
            PlanStage planStage = planStageService.getPlanStageByBatchProductIdAndName(productManufactInfor.getBatchProductId(),"生产装配");
            planStage.setStageEndTime(findate);
            PlanStage planStage2 = planStageService.getPlanStageByBatchProductIdAndName(productManufactInfor.getBatchProductId(),"打包入库");
            planStage.setStageStartTime(findate);
            planStageRepository.save(planStage);
            planStageRepository.save(planStage2);
        }
        return 0; //"工序完成执行";
    }


    @Override
    public ProductManufactInfor pauseTimeAndUpdateCap(ProductManufactInfor productManufactInfor) {
        // 暂停计时
        productManufactInforService.pauseTiming(productManufactInfor.getId());
        productManufactInfor.setProcessStatus(3);// 已完成
        productManufactInfor.setManufactEndDate(new Date());
        return productManufactInforRepository.save(productManufactInfor);

//        // 生成实际产能日历
//        plantCapacityCalendarService.generateRealCapacityCalendar(save);

    }

    /**
     * 手动排程
     *
     * @param workOrderProductPlanDto
     */
    @Override
    public void manualSchedule(WorkOrderProductPlanDto workOrderProductPlanDto) {
        WorkOrderInfor workOrder = workOrderInforRepository.findWorkOrderInforByIdAndDelete(workOrderProductPlanDto.getWoId(), 0);
        // 检查是否上传工时/指导书
        checkGuideBookAndWorkHourUploaded(Collections.singletonList(workOrder.getBatchProductId()));
        BatchProduct product = batchProductRepository.findBatchProductByIdAndDelete(workOrder.getBatchProductId(), 0);
        productManufactInforService.updateProductPlanTime(workOrderProductPlanDto,true);
        // 设置已排程
        product.setIsPoReleased(1);
        product =  batchProductRepository.save(product);
        // 检查是否都有检验单模板
        checkTemplate(workOrder);
        // 直接释放工单， 可以新开一个线程进行
        ReleaseWoTask releaseWoTask = new ReleaseWoTask(workOrder);
        taskThreadPool.execute(releaseWoTask);


        //-----------------------------------------------------------------------
        // 操作人 发送  通知给  项目经理
        String operatorName= workOrderProductPlanDto.getOperatorName();
        String operatorId= workOrderProductPlanDto.getOperatorName();
        if(operatorName==null){
            operatorName="-";
        }

        String receiverId=null;
        String receiverName=null;
        String infoId = workOrder.getInfoId();
        Info info = infoRepository.findInfoById(infoId);
        String teamId= info.getTeamId();
        TeamInfo teamInfo = teamInfoRepository.findTeamInfoByTeamIdAndCategoryAndDelete(teamId,"项目经理",0);
        if(teamInfo!=null){
            receiverId=teamInfo.getUserId();
            receiverName=teamInfo.getUserName();
        }

        NotifyInfo notifyInfo =new NotifyInfo();
        notifyInfo.setModuleName("生产制造");
        notifyInfo.setFuncName("生产排程");
        notifyInfo.setNotifyDesc("提示用户ERP进行工单号为["+workOrder.getWo()+"]的领用");
        notifyInfo.setNotifyType("通知");


        notifyInfo.setSenderName(operatorName);
        notifyInfo.setSenderId(operatorId);
        notifyInfo.setSendTime(product.getUpdateTime());

        notifyInfo = notifyInfoRepository.save(notifyInfo);
        notifyTemplateInfoService.sendNotify(notifyInfo,-1,receiverName,receiverId);
    }



    public void checkTemplate(WorkOrderInfor workOrder){

        // 查找终检单模板
        List<InspectionTemplate> templatelist = inspectionTemplateRepository.findInspectionTemplateByStateAndDeleteAndType("1", 0, "终检");
        if (templatelist.size() == 0) throw new BeadminException("未找到已发布的终检检验表模板");
        // 检查工序自检单的模板是否存在, 所有工序， 需要自检的去检查其模板是否存在；
        //
        List<String> noSelfCheckTemplateProcess = workOrderInforRepository.findNoSelfCheckTempleteProcess(workOrder.getWo(), workOrder.getProductType());
        if (noSelfCheckTemplateProcess.size()!=0) {
            StringBuilder sb = new StringBuilder();
            sb.append("排程失败，有工序没有自检模板。柜体类型：")
                    .append(workOrder.getProductType())
                    .append("工序：")
                    .append(String.join(",",noSelfCheckTemplateProcess));
            throw new BeadminException(sb.toString());
        }
    }
    /**
     * 对多个工单排程
     *
     * @param scheduleDto
     */
    @Override
    public void scheduleByWoIds(ScheduleDto scheduleDto, boolean isManual) {
        List<String> woIds = scheduleDto.getWoIds();
        // 检查是否属于同一批次
        productManufactInforService.checkSameBatchPlan(woIds);

        // 检查是否上传工时/指导书
        List<String> batchProductIds = workOrderInforRepository.findBatchProductIdsByWorkOrderInforIdsAndDelete(woIds,0);
        checkGuideBookAndWorkHourUploaded(batchProductIds);

        woIds.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                WorkOrderProductPlanDto workOrderProductPlanDto = new WorkOrderProductPlanDto();
                workOrderProductPlanDto.setWoId(s);
                workOrderProductPlanDto.setProductPlanTimeDto(scheduleDto.getProductPlanTimeDto());
                productManufactInforService.updateProductPlanTime(workOrderProductPlanDto,isManual);
                WorkOrderInfor workOrder = workOrderInforRepository.findWorkOrderInforByIdAndDelete(s, 0);
                // 检查是否都有检验单模板
                checkTemplate(workOrder);
                ReleaseWoTask releaseWoTask = new ReleaseWoTask(workOrder);
                taskThreadPool.execute(releaseWoTask);
            }
        });


    }

    public void checkGuideBookAndWorkHourUploaded(List<String> batchProductIds){

        List<BatchProduct> batchProducts = batchProductRepository.findBatchProductsByIdInAndDelete(batchProductIds, 0);

        for (BatchProduct product: batchProducts) {
            if (product.getIsStandard()==0 && product.getIsStdWorkHourUploaded()==0){
                throw new BeadminException("柜体编码【"+product.getProductCode()+"】工单工时周期未设置");
            }


            if (product.getIsStandard()==0 && product.getIsGuideBookUploaded() <= 0){
                throw new BeadminException("柜体编码【"+product.getProductCode()+"】指导书未上传");
            }

        }

    }

}
